#include <vector>
#include <string>

class VMode 
{
public: 
    using Candidates = std::vector<std::string>;
    enum CandType
    {
        ET_INVALID, //原始输入（非法输入)
        ET_DIGIT, //数字
        ET_DATE, //日期
        ET_EXPV, //表达式值
        ET_UNCMPLT //不完整输入
    };
public:
    VMode();
    ~VMode();
    const Candidates &Decode(const std::string &vstr);
    void Clear();
    const std::string &GetComposition(void) { return _input; }
    CandType CandidateType(void) { return _cand_type; }
    //idx: start from 0
    const std::string Select(int idx);
    
private:
    void lexer();
    double calculate(int s, int e);
    double calculate_func(int func, int s, int e);
    double calculate_avg(int s, int e);
    double calculate_var(int s, int e);
    double calculate_min(int s, int e);
    double calculate_max(int s, int e);
    int find_operator(int level, int s, int e);
    int find_comma(int s, int e);
    double calculate_op(int op, double arg1, double arg2);

private:
    struct VModeToken
    {
        VModeToken(int t, long long i = 0) : type(t), iv(i) {}
        int type;
        union
        {
            long long iv; //int value, token id, close parentheses index
            double dv; //double value
        };
    };
private:
    CandType _cand_type; //VMode输入状态
    Candidates _cands;
    std::string _input; //历史输入
    std::vector<VModeToken> _tk_list;
    int _ecode;
    double _isign;
};
